'''
Created on 2009-11-18

@author: yuchen
'''

import ai.abstract_player
import gamemodel.SubNeighborhood5x5 as mNB
import computerHeuri
import random

class AIcomputer(ai.abstract_player.AIPlayer):
	
	def __init__(self, player):
		ai.abstract_player.AIPlayer.__init__(self, player)
		self.tempoPiece = [None, None, None, None]
		self.player = [None, None]
		self.tempoState = 1
		self.drawCondition1 = [0, 0, 0, 0]
		self.drawCondition2 = 0
		self.drawCondition3 = [0, 0]
		
	def get_move(self, state):
		# get all moves
		moves = state.successorMove()
		player = state.getCurrentPlayer()			 
		if moves == None :						 
			return None
		elif len(moves) == 1:
			return moves[0]
		
		if self.get_draw(state) == True :
			return 'draw'
		

		mentoCarloAvailable = True
		for element in moves :
			currentPiece = state.board.getBoardPosition(element.list[0].original[0], element.list[0].original[1], player)
			if currentPiece.king == True :
				mentoCarloAvailable = False
		
		if mentoCarloAvailable == True :
			move = moves[self.get_menteCarlo(state)]
		else :
			move = computerHeuri.AIcomputer(ai.abstract_player.AIPlayer).get_move(state)
		
				
		return move
	
	
	def get_menteCarlo(self, state):
		player = state.getCurrentPlayer()
		currentState = state.get_copy()
		states = currentState.Successor()
		moves = currentState.successorMove()
		probability = dict()
		totalValue = 0.0
		counter = 0
	
		length1 = len(states)
		for x in range(length1) :
			probability[x] = 0
			counter = 1
			length2 = len(moves[x].list)
			for y in range(length2):
				prob = 0
				counter += 1
				sub_neighbors = mNB.Neighbor55.constructFromState(states[x], moves[x].list[y].original[0], moves[x].list[y].original[1], player)
				tempZ = -1
				tempW = -1
				length3 = len(sub_neighbors)
				for z in range(length3) :
					tempProb = 0
					w = -1
					if z != None and sub_neighbors[z] != None:
						if z == 0 or z == 2 :
							if y >= length2 - 1 :
								if abs(moves[x].list[y].original[0] - moves[x].list[y].destination[0]) == 1 :
									prob = (prob + sub_neighbors[z].getMoveProb(0))
									w = 0
								if abs(moves[x].list[y].original[0] - moves[x].list[y].destination[0]) == 2 and abs(moves[x].list[y].original[1] - moves[x].list[y].destination[1]) == 2 :
									prob = (prob + sub_neighbors[z].getMoveProb(0))
									w = 0
							else :
								if moves[x].list[y].original[0] == moves[x].list[y + 1].destination[0] and abs(moves[x].list[y].original[1] - moves[x].list[y + 1].destination[1]) == 4 :
									prob = (prob + sub_neighbors[z].getMoveProb(1))
									w = 1
								if abs(moves[x].list[y].original[0] - moves[x].list[y + 1].destination[0]) == 4 and abs(moves[x].list[y].original[1] - moves[x].list[y + 1].destination[1]) == 4 :
									prob = (prob + sub_neighbors[z].getMoveProb(2))
									w = 2
								y += 1
							if prob >= tempProb :
								tempProb = prob
								tempZ = z
								tempW = w
						if z == 1 :
							if y >= length2 - 1 :
								if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == 1 :
									prob = (prob + sub_neighbors[z].getMoveProb(0))
									w = 0 
								if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == 2 and moves[x].list[y].original[1] - moves[x].list[y].destination[1] == -2 :
									prob = (prob + sub_neighbors[z].getMoveProb(0))
									w = 0 
								if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == -1 :
									prob = (prob + sub_neighbors[z].getMoveProb(1))
									w = 1
								if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == -2 and moves[x].list[y].original[1] - moves[x].list[y].destination[1] == -2 :
									prob = (prob + sub_neighbors[z].getMoveProb(1))
									w = 1
							else :
								if moves[x].list[y].original[0] != moves[x].list[y + 1].destination[0] :
									if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == 1 :
										prob = (prob + sub_neighbors[z].getMoveProb(0))
										w = 0
									if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == 2 and moves[x].list[y].original[1] - moves[x].list[y].destination[1] == -2 :
										prob = (prob + sub_neighbors[z].getMoveProb(0))
										w = 0
									if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == -1 :
										prob = (prob + sub_neighbors[z].getMoveProb(1))
										w = 1
									if moves[x].list[y].original[0] - moves[x].list[y].destination[0] == -2 and moves[x].list[y].original[1] - moves[x].list[y].destination[1] == -2 :
										prob = (prob + sub_neighbors[z].getMoveProb(1))
										w = 1
								if moves[x].list[y].original[0] == moves[x].list[y + 1].destination[0] :
									if moves[x].list[y].original[1] - moves[x].list[y].destination[1] == -2 :
										prob = (prob + sub_neighbors[z].getMoveProb(2))
										w = 2
									if moves[x].list[y].original[1] - moves[x].list[y].destination[1] == 2 :
										prob = (prob + sub_neighbors[z].getMoveProb(3))
										w = 3
									y += 1
							if prob >= tempProb :
								tempProb = prob
								tempZ = z
								tempW = w
				#TODO a
				probability[x] = probability[x] + tempProb
			probability[x] = probability[x] * 1.0 / counter
			totalValue = totalValue + probability[x]
		
		randomValue = random.uniform(0, totalValue)
		tempValue =  0
		tempNumber = None
		for returnedNumber in probability :
			tempValue = tempValue + probability[returnedNumber]
			tempNumber = returnedNumber
			if tempValue > randomValue :
				return returnedNumber
		return tempNumber

	def get_draw(self, state):
		moves = state.successorMove()
		player = state.getCurrentPlayer()
		if self.player[0] == None :
			self.player[0] = state.board.getPlayer0()
			self.player[1] = state.board.getPlayer1()
			number = 0
		else :
			if self.player[0] == player :
				number = 0
			else :
				number = 1
				
		# judge whether a state has been repeated 3 times
		self.tempoState = 1 - self.tempoState
		tempPiece0 = []
		tempPiece1 = []
		for piece in self.player[number].pieces :
			tempPiece0.append(piece.position)
		tempPiece0.sort()
		
		for piece in self.player[1 - number].pieces :
			tempPiece1.append(piece.position)
		tempPiece1.sort()
		
		if self.tempoPiece[number + 2 * self.tempoState] == None :
			self.tempoPiece[number + 2 * self.tempoState] = tempPiece0
			self.tempoPiece[1 - number + 2 * self.tempoState] = tempPiece1
			self.drawCondition1[number + 2 * self.tempoState] += 1
		else :
			if self.tempoPiece[number + 2 * self.tempoState] == tempPiece0 and\
			self.tempoPiece[1 - number + 2 * self.tempoState] == tempPiece1 :
				self.drawCondition1[number + 2 * self.tempoState] += 1
			else :
				self.tempoPiece[number + 2 * self.tempoState] = tempPiece0
				self.tempoPiece[1 - number + 2 * self.tempoState] = tempPiece1
				self.drawCondition1[number + 2 * self.tempoState] = 1
		
		if self.drawCondition1[number + 2 * self.tempoState] == 3 :
			return True
		
		# only move king and do not eat any piece in 25 turns
		currentPiece = state.board.getBoardPosition(moves[number].list[0].original[0], moves[number].list[0].original[1], player)
		if currentPiece.king == True and\
		abs(moves[number].list[0].original[0] - moves[number].list[0].destination[0]) == 1 and\
		abs(moves[number].list[0].original[1] - moves[number].list[0].destination[1]) == 1 :
			self.drawCondition2 += 1
		else :
			self.drawCondition2 = 0
		
		if self.drawCondition2 == 50 :
			return True
		
		# if one player have less than 3 pieces, and the other one player has only one king in 16 turns.
		if len(tempPiece0) <= 3 and len(tempPiece1) == 1 :
			if self.player[1 - number].pieces.king == True :
				self.drawCondition3[number] += 1
		
		if self.drawCondition3[number] == 16 :
			return True
		
		return False